package com.ruoyi.common.redis.service;

import com.ruoyi.common.redis.functions.MethodsSupplier;
import com.ruoyi.common.redis.pojo.CacheObject;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 本地化缓存,缓存信息需要本地处理
 *
 * @author zhanglianbao
 **/
@Component
public class LocalCache {

  final ConcurrentHashMap<String, CacheObject<?>> cacheMap = new ConcurrentHashMap<>();

  @Value("${pet.food.cache.expireTimeRange:5}")
  private long expireTimeRange;
  @Resource
  public RedisService redisService;

  private static final String CACHE_KEY_PREFIX = "localCache:";

  public <T> T get(String key, MethodsSupplier<T> methodSupplier) {
    if (cacheMap.containsKey(key)) {
      // 判断缓存是否过期
      final CacheObject<?> cacheObject = cacheMap.get(key);
      if (cacheObject.getExpireTime() > System.currentTimeMillis()) {
        return (T) cacheObject.getValue();
      }
    }
    final CacheObject<T> fromRemote = getFromRemote(key, methodSupplier);
    cacheMap.put(key, fromRemote);
    return fromRemote.getValue();
  }

  private <T> CacheObject<T> getFromRemote(String key, MethodsSupplier<T> methodSupplier) {
    final String redisCacheKey = redisCacheKey(key);
    //redis 中取值
    final T cacheObject = redisService.getCacheObject(redisCacheKey);
    if (cacheObject == null) {
      //业务传递
      final T data = methodSupplier.exec();
      redisService.setCacheObject(redisCacheKey, data, 60 * 60 * 24L, TimeUnit.SECONDS);
      return new CacheObject<T>().setKey(key).setValue(data)
          .setExpireTime(System.currentTimeMillis() + expireTimeRange * 1000L);
    }
    return new CacheObject<T>().setKey(key).setValue(cacheObject)
        .setExpireTime(System.currentTimeMillis() + expireTimeRange * 1000L);
  }

  private String redisCacheKey(String key) {
    return CACHE_KEY_PREFIX + key;
  }

  public void refresh(String feedAmountRuleKey) {
    cacheMap.remove(feedAmountRuleKey);
    redisService.deleteObject(redisCacheKey(feedAmountRuleKey));
  }

  public long getExpireTime() {
    return this.expireTimeRange;
  }
}
